/*
 #
 #  Files       : Vector.h
 #                ( C++ header file )
 #
 #  Description : The SmallMatrix Library
 #                ( http://code.google.com/p/smallmatrix )
 #
 #  Copyright   : Olivier Juan
 #                ( http://www.mas.ecp.fr/vision/Personnel/juan/ )
 #
 #  License     : CeCILL-C
 #                ( http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html )
 #
 #  This software is governed by the CeCILL-C license under French law and
 #  abiding by the rules of distribution of free software.  You can  use,
 #  modify and or redistribute the software under the terms of the CeCILL-C
 #  license as circulated by CEA, CNRS and INRIA at the following URL
 #  "http://www.cecill.info".
 #
 #  As a counterpart to the access to the source code and  rights to copy,
 #  modify and redistribute granted by the license, users are provided only
 #  with a limited warranty  and the software's author,  the holder of the
 #  economic rights,  and the successive licensors  have only  limited
 #  liability.
 #
 #  In this respect, the user's attention is drawn to the risks associated
 #  with loading,  using,  modifying and/or developing or reproducing the
 #  software by the user in light of its specific status of free software,
 #  that may mean  that it is complicated to manipulate,  and  that  also
 #  therefore means  that it is reserved for developers  and  experienced
 #  professionals having in-depth computer knowledge. Users are therefore
 #  encouraged to load and test the software's suitability as regards their
 #  requirements in conditions enabling the security of their systems and/or
 #  data to be ensured and,  more generally, to use and operate it in the
 #  same conditions as regards security.
 #
 #  The fact that you are presently reading this means that you have had
 #  knowledge of the CeCILL-C license and that you accept its terms.
 #
*/

#ifndef _SMALLMATRIX_VECTOR_H
#define _SMALLMATRIX_VECTOR_H
#include "MatrixBase.h"

//////////////////////////////////////////////////////////////////////
//
// - JUAN Olivier 15/03/2005 --> Release Candidate 2
//                           --> Joyeuse Paques (bientot)
//
//////////////////////////////////////////////////////////////////////


NAMESPACE_BEGIN(SmallMatrix)

template <typename T, int M> class Vector : public Matrix_Base<Vector<T, M> >
{
public:
	typedef Vector<T, M> T_vector;
private:
	typedef Matrix_Base<T_vector > Base;
public:
	//typedef typename Base::value_type value_type;
	//typedef typename Base::pointer pointer;
	//typedef typename Base::const_pointer const_pointer;
	//typedef typename Base::reference reference;
	//typedef typename Base::const_reference const_reference;
	//typedef typename Base::size_type size_type;
	//typedef typename Base::difference_type difference_type;

public:
	template <int IdxR, int IdxC>
		reference Access() {
			STATIC_ASSERT((IdxR<M)&&(IdxR>=0));
			STATIC_ASSERT(IdxC==0);
			return Base::template dataAccess<IdxR>();
		}
	template <int IdxR, int IdxC>
		const_reference Acess() const {
			STATIC_ASSERT((IdxR<M)&&(IdxR>=0));
			STATIC_ASSERT(IdxC==0);
			return Base::template dataAccess<IdxR>();
		}
	template <int IdxR>
		reference Access() {
			STATIC_ASSERT((IdxR<M)&&(IdxR>=0));
			//STATIC_ASSERT(IdxC==0);
			return Base::template dataAccess<IdxR>();
		}
	template <int IdxR>
		const_reference Acess() const {
			STATIC_ASSERT((IdxR<M)&&(IdxR>=0));
			//STATIC_ASSERT(IdxC==0);
			return Base::template dataAccess<IdxR>();
		}
public:

    // Constructor added by Peter Nordlund
    //template<typename P_expr>
    //inline TinyVector(_bz_VecExpr<P_expr> expr);
	INLINE Vector(): Base(){};
	INLINE Vector(const value_type x[Base::SIZE]) : Base(x){}
	template <typename TT> INLINE Vector(const TT& copy) : Base(copy){}
	//template <typename TT> INLINE Vector(const Matrix_Base<TT>& copy) : Base(copy){}
	INLINE Vector(const Vector<value_type, M>& copy) : Base(copy){}
	template <typename value_type2>
	INLINE Vector(const Vector<value_type2, M>& copy) : Base(copy){}
	INLINE Vector(const_reference x) : Base(x) {}										// Pour tout M
	INLINE Vector(const_reference x0, const_reference x1) {
		Access<0>() = x0;
		Access<1>() = x1;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4, const_reference x5) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
		Access<5>() = x5;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4, const_reference x5, const_reference x6) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
		Access<5>() = x5;
		Access<6>() = x6;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4, const_reference x5, const_reference x6,
		const_reference x7) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
		Access<5>() = x5;
		Access<6>() = x6;
		Access<7>() = x7;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4, const_reference x5, const_reference x6,
		const_reference x7, const_reference x8, const_reference x9) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
		Access<5>() = x5;
		Access<6>() = x6;
		Access<7>() = x7;
		Access<8>() = x8;
		Access<9>() = x9;
	}
	INLINE Vector(const_reference x0, const_reference x1, const_reference x2, 
		const_reference x3, const_reference x4, const_reference x5, const_reference x6,
		const_reference x7, const_reference x8, const_reference x9, const_reference x10) {
		Access<0>() = x0;
		Access<1>() = x1;
		Access<2>() = x2;
		Access<3>() = x3;
		Access<4>() = x4;
		Access<5>() = x5;
		Access<6>() = x6;
		Access<7>() = x7;
		Access<8>() = x8;
		Access<10>() = x10;
	}

	//INLINE Vector(const value_type& x0, const value_type& x1, const value_type& x2);	// M=3
	//INLINE Vector(const value_type& x0, const value_type& x1, const value_type& x3,		// M=4
	//	const value_type& x3);
	INLINE ~Vector() {};


	//template <typename TT> INLINE Vector<M>& operator=(const Matrix_Base<TT>& copy) {
	//	Base& ref=*this; 
	//	return ref = copy;
	//}
	//template <typename TT> INLINE Vector<M>& operator=(const TT& copy) {
	//	Base& ref=*this;
	//	return ref = copy;
	//}
	//INLINE Vector<M>& operator=(const Vector<M>& copy) {
	//	Base& ref=*this;
	//	return ref = copy;
	//}
	INLINE reference operator()(const int& idx, const int& null=0)
	{
		assert((idx>=0)&&(idx<M)&&(null==0));
		T_vector& ref = *this;
		return ref[idx];
	}
	INLINE const_reference operator()(const int& idx, const int& null=0) const
	{
		assert((idx>=0)&&(idx<M)&&(null==0));
		const T_vector& ref = *this;
		return ref[idx];
	}
	//template <typename T1,typename T2> INLINE Vector<M>& prod(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2);
	//template <typename T1,typename T2> INLINE Vector<M>& add(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2);
	//template <typename T1,typename T2> INLINE Vector<M>& subst(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2);
	//template <typename T1> INLINE Vector<M>& add(const Matrix_Base<T1>& M1);
	//template <typename T1> INLINE Vector<M>& subst(const Matrix_Base<T1>& M1);
	//template <typename T1> INLINE Vector<M>& mult(const Matrix_Base<T1>& M1);
	//template <typename T1> INLINE Vector<M>& div(const Matrix_Base<T1>& M1);
	//INLINE reel dot(const Vector<M>& Two)const;
	//template <int P> INLINE Matrix<M,P> outer_product(const Vector<P>& Two)const;
	//INLINE SquareMatrix<M> outer_product(const Vector<M>& Two)const;
	//INLINE T_vector operator^(const T_vector&v) const;
	//INLINE bool operator<(const T_vector& test)const;
	//INLINE T_vector& normalize();
};

//template <typename T, int M> 
//INLINE
//Vector<T, 2>::Vector(const T& x0,const T& x1) : Matrix_Base<Vector<T, 2> >(){
//	//Vector<T, 2>& ref = *this;
//}

//template <> 
//INLINE Vector<3>::Vector(const reel &x,const reel &y,const reel &z):Matrix_Base<Vector<3> >(){
//	Vector<3>& ref = *this;
//	ref.Access<0,0>()=x;ref.Access<1,0>()=y;ref.Access<2,0>()=z;
//}
//
//template <> 
//INLINE Vector<4>::Vector(const reel &x,const reel &y,const reel &z,const reel &t):Matrix_Base<Vector<4> >(){
//	Vector<4>& ref = *this;
//	ref.Access<0,0>()=x;ref.Access<1,0>()=y;ref.Access<2,0>()=z;ref.Access<3,0>()=t;
//}
//
//#pragma warning( disable : 4100)
////! Read/Write Accessor
//template <int M> INLINE reel& Vector<M>::operator ()(const int& idx,const int& null)
//{
//	assert((idx>=0)&&(idx<M)&&(null==0));
//	Vector<M>& ref = *this;
//	return ref[idx];
//}
////! Read Only Accessor
//template <int M> INLINE const reel& Vector<M>::operator ()(const int& idx,const int& null)const
//{
//	assert((idx>=0)&&(idx<M)&&(null==0));
//	const Vector<M>& ref = *this;
//	return ref[idx];
//}
//#pragma warning( default : 4100)
//
//////! Matrix-Matrix Product in which the result is a Vector
////template <int M> template <typename T1,typename T2> INLINE Vector<M>& Vector<M>::prod(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2) {
////	Vector<M>& ref = *this;
////	for (int i=0;i<M;i++)
////		for (int k=0;k<T2::ROW;k++)
////			ref(i,0)+=M1(i,k)*M2(k,0);
////	return ref;
////}
//////! Matrix-Matrix Sum in which the result is a Vector
////template <int M> template <typename T1,typename T2> INLINE Vector<M>& Vector<M>::add(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++)
////		ref(i,0)=M1(i,0)+M2(i,0);
////	return ref;
////}
//////! Matrix-Matrix Substract in which the result is a Vector
////template <int M> template <typename T1,typename T2> INLINE Vector<M>& Vector<M>::subst(const Matrix_Base<T1>& M1,const Matrix_Base<T2>& M2) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++)
////		ref(i,0)=M1(i,0)-M2(i,0);
////	return ref;
////}
//////! Matrix-Matrix Sum in which the result is a Vector
////template <int M> template <typename T1> INLINE Vector<M>& Vector<M>::add(const Matrix_Base<T1>& M1) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++)
////		ref(i,0)+=M1(i,0);
////	return ref;
////}
//////! Matrix-Matrix Substract in which the result is a Vector
////template <int M> template <typename T1> INLINE Vector<M>& Vector<M>::subst(const Matrix_Base<T1>& M1) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++)
////		ref(i,0)-=M1(i,0);
////	return ref;
////}
////template <int M> template <typename T1> INLINE Vector<M>& Vector<M>::mult(const Matrix_Base<T1>& M1) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++)
////		ref(i,0)*=M1(i,0);
////	return ref;
////}
////template <int M> template <typename T1> INLINE Vector<M>& Vector<M>::div(const Matrix_Base<T1>& M1) {
////	Vector<M>& ref=*this;
////	for (int i=0;i<M;i++) {
////		assert(M1(i,0)!=0);
////		ref(i,0)/=M1(i,0);
////	}
////	return ref;
////}
//////! Inner Product with the Vector \a Two
////template <int M> INLINE reel Vector<M>::dot(const Vector<M> &Two)const
////{
////	const Vector<M>& ref=*this;
////	return ref.Access<M-1,0>()*Two.Access<M-1,0>()+(*((const Vector<M-1>*)(this))).dot(*((const Vector<M-1>*)(&Two)));
////}
////template <> INLINE reel Vector<1>::dot(const Vector<1> &Two)const
////{
////	const Vector<1>& ref=*this;
////	return ref.Access<0,0>()*Two.Access<0,0>();
////}
//////! Outer Product (*this) * Two'
////template <int M> template <int P> INLINE Matrix<M,P> Vector<M>::outer_product(const Vector<P> &Two)const
////{
////	const Vector<M>& ref=*this;
////	Matrix<M,P> A;
////	for (int i=0; i<M; i++)
////		for (int j=0; j<P; j++)
////			A(i,j)=ref(i)*Two(j);
////	return A;
////}
////template <int M> INLINE SquareMatrix<M> Vector<M>::outer_product(const Vector<M> &Two)const
////{
////	const Vector<M>& ref=*this;
////	SquareMatrix<M> A;
////	for (int i=0; i<M; i++)
////		for (int j=0; j<M; j++)
////			A(i,j)=ref(i)*Two(j);
////	return A;
////}
//template <int M> INLINE bool Vector<M>::operator<(const Vector<M>& test)const
//{
//	const Vector<M>& ref=*this;
//	bool res=true;
//	int i=0;
//	while((res)&&(i<M))
//	{
//		res=(ref[i]==test[i]);
//		i++;
//	}
//	i--;
//	return (res?false:(ref[i]<test[i]));
//}
//template <>
//INLINE Vector<3> Vector<3>::operator^(const Vector<3>&v) const {
//	const Vector<3>& ref = *this;
//	return Vector<3>(ref[1]*v[2]-ref[2]*v[1], -ref[0]*v[2]+ref[2]*v[0], ref[0]*v[1]-ref[1]*v[0]);
//}
//template <int M>
//Vector<M>& Vector<M>::normalize() 
//{
//	return ((*this) /= Base::norm());
//}
//

NAMESPACE_END

#endif
